---
title: 'Node'
sidebarTitle: 'Node'
icon: 'node'
---

The backend SDK lets you interact with the Nango API. It is available on [NPM](https://www.npmjs.com/package/@nangohq/node) as `@nangohq/node`.

## Instantiate the backend SDK

Install it with your favorite package manager, e.g.:

```bash
npm i -S @nangohq/node
```

Instantiate the `Nango` class:

```js
import { Nango } from '@nangohq/node';

const nango = new Nango({ secretKey: '<SECRET-KEY>' });
```

**Parameters**

<Expandable>
  <ResponseField name="config" type="object" required>
    <Expandable title="config" defaultOpen>
      <ResponseField name="secretKey" type="string" required>
        Get your secret key in the environment settings of the Nango UI. THis key should never be shared.
      </ResponseField>

      <ResponseField name="host" type="string">
        Omitting the host points to Nango Cloud. For local development, use `http://localhost:3003`. Use your instance URL if self-hosting.
      </ResponseField>
    </Expandable>
  </ResponseField>
</Expandable>

## Rate limits

The Nango SDK is rate-limited to prevent abuse and ensure fair usage across all clients. The rate limit is enforced on a per-account basis, with a fixed window of time and a maximum number of requests allowed within that window.

If a client exceeds the rate limit, the API will respond with a 429 `Too Many Requests` status code. In this case, the `Retry-After` header is included, indicating the number of seconds the client should wait before making another request to avoid being rate-limited.

To handle rate limiting gracefully, clients should monitor for the 429 status code and honor the `Retry-After` header value provided in the response.

```js
// Example:
try {
    const res = await nango.listIntegrations();
    ...
} catch(err) {
    if (err.response.status === 429) {
        const retryAfter = err.response.headers['retry-after'];
        // wait and retry
        ...
    }
    ...
}
```

## Providers

### List all providers

Returns a list of providers.

```js
await nango.listProviders()
```

**Example Response**

<Expandable>
```json
{
    "data": [
        {
            "name": "posthog",
            "categories": ["dev-tools"],
            "auth_mode": "API_KEY",
            "proxy": {
                "base_url": "https://api.posthog.com",
            },
            "docs": "https://nango.dev/docs/integrations/all/posthog"
        }
    ]
}
```
</Expandable>


### Get a provider

Returns a specific provider.

```js
await nango.getProvider({ provider: <NAME> })
```

**Example Response**

<Expandable>
```json
{
    "data": {
        "name": "posthog",
        "categories": ["dev-tools"],
        "auth_mode": "API_KEY",
        "proxy": {
            "base_url": "https://api.posthog.com",
        },
        "docs": "https://nango.dev/docs/integrations/all/posthog"
    }
}
```
</Expandable>

## Integrations

### List all integrations

Returns a list of integrations.

```js
await nango.listIntegrations()
```

**Example Response**

<Expandable>
```json
{
    "configs": [
        {
            "unique_key": "slack-nango-community",
            "provider": "slack",
            "logo": "http://localhost:3003/images/template-logos/slack.svg",
            "created_at": "2023-10-16T08:45:26.241Z",
            "updated_at": "2023-10-16T08:45:26.241Z",
        },
        {
            "unique_key": "github-prod",
            "provider": "github",
            "logo": "http://localhost:3003/images/template-logos/github.svg",
            "created_at": "2023-10-16T08:45:26.241Z",
            "updated_at": "2023-10-16T08:45:26.241Z",
        },
    ]
}
```
</Expandable>

### Get an integration

Returns a specific integration.

```js
await nango.getIntegration({ uniqueKey: <UNIQUE_KEY> });

// Deprecated
await nango.getIntegration(<INTEGRATION-ID>);
```

**Parameters**

<Expandable>
    <ResponseField name="uniqueKey" type="string" required>
         The integration ID
    </ResponseField>
    <ResponseField name="include" type="array">
        Include sensitive data. Allowed values: `webhook`
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "data": {
        "unique_key": "slack-nango-community",
        "provider": "slack",
        "logo": "http://localhost:3003/images/template-logos/slack.svg",
        "created_at": "2023-10-16T08:45:26.241Z",
        "updated_at": "2023-10-16T08:45:26.241Z",
    }
}
```
</Expandable>

### Create an integration

Create a new integration.

```js
await nango.createIntegration({ provider: <PROVIDER-ID>, unique_key: <UNIQUE_KEY>, [...] });

// Deprecated
await nango.createIntegration(<PROVIDER-ID>, <INTEGRATION-ID>);
```

**Parameters**

<Expandable>
    <ResponseField name="provider" type="string" required>
        The ID of the API provider in Nango (cf. [providers.yaml](https://nango.dev/providers.yaml) for a list of API provider IDs.)
    </ResponseField>

    <ResponseField name="unique_key" type="string" required>
        The integration ID.
    </ResponseField>

    <ResponseField name="display_name" type="string">
        The display name of this integration
    </ResponseField>

    <ResponseField name="credentials" type="Record<string, string>">
        The credentials to include depend on the specific integration that you want to create.
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "data": {
        "unique_key": "slack-nango-community",
        "provider": "slack",
        "logo": "http://localhost:3003/images/template-logos/slack.svg",
        "created_at": "2023-10-16T08:45:26.241Z",
        "updated_at": "2023-10-16T08:45:26.241Z",
    }
}
```
</Expandable>

### Update an integration

Patch an integration, all fields are optional.

```js
await nango.updateIntegration({ uniqueKey: <UNIQUE_KEY> }, { [...body] });

// Deprecated
await nango.updateIntegration(<PROVIDER-ID>, <INTEGRATION-ID>);
```

**Parameters**

<Expandable>
    <ResponseField name="unique_key" type="string">
        The integration ID.
    </ResponseField>

    <ResponseField name="display_name" type="string">
        The display name of this integration
    </ResponseField>

    <ResponseField name="credentials" type="Record<string, string>">
        The credentials to include depend on the specific integration that you want to create.
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "data": {
        "unique_key": "slack-nango-community",
        "provider": "slack",
        "logo": "http://localhost:3003/images/template-logos/slack.svg",
        "created_at": "2023-10-16T08:45:26.241Z",
        "updated_at": "2023-10-16T08:45:26.241Z",
    }
}
```
</Expandable>

### Delete an integration

Deletes a specific integration.

```js
await nango.deleteIntegration(<UNIQUE_KEY>);
```

**Parameters**

<Expandable>
    <ResponseField name="uniqueKey" type="string" required>
        The integration ID.
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "success": true
}
```
</Expandable>

## Connections

### List connections

Returns a list of connections without credentials.

```js
await nango.listConnections({
    connectionId: 'connection-id',
    userId: 'user-123',
    integrationId: 'integration-456',
    // only supports email | displayName
    tags: { displayName: 'My User' }
});
```

**Parameters**

<Expandable>
    <ResponseField name="params" type="object">
        <Expandable title="params" defaultOpen>
            <ResponseField name="connectionId" type="string">
                Optional. Will exactly match a given connectionId. Can return multiple connections with the same ID across integrations.
            </ResponseField>
            <ResponseField name="userId" type="string">
                Optional. Will exactly match a given end user ID.
            </ResponseField>
            <ResponseField name="integrationId" type="string">
                Optional. Filter by integration ID.
            </ResponseField>
            <ResponseField name="tags" type="Record<string, string>">
                Optional. Filter by tags associated with connections.
            </ResponseField>
        </Expandable>
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "connections": [
        {
            "id": 1,
            "connection_id": "test-1",
            "provider": "slack",
            "provider_config_key": "slack-nango-community",
            "created": "2023-06-03T14:53:22.051Z",
            "metadata": null,
            "errors": []
        },
        {
            "id": 2,
            "connection_id": "test-2",
            "provider": "slack",
            "provider_config_key": "slack-nango-community",
            "created": "2023-06-03T15:00:14.945Z",
            "metadata": {
                "bot_id": "some-uuid"
            },
            "errors": [{ "type": "auth", "log_id": "VrnbtykXJFckCm3HP93t"}],
            "end_user": {
                "id": "your-internal-id",
                "email": "user@example.com",
                "organization": {
                    "id": "user-organization-id"
                }
            }
        }
    ]
}
```
</Expandable>

### Get a connection (with credentials)

Returns a specific connection with credentials.

```js
await nango.getConnection(<INTEGRATION-ID>, <CONNECTION-ID>);
```

<Info>
The response content depends on the API authentication type (OAuth 2, OAuth 1, API key, Basic auth, etc.).

If you do not want to deal with collecting & injecting credentials in requests for multiple authentication types, use the Proxy ([step-by-step guide](/implementation-guides/requests-proxy/implement-requests-proxy)).
</Info>

<Tip>
When you fetch the connection with this API endpoint, Nango will check if the access token has expired. If it has, it will refresh it.

We recommend not caching tokens for longer than 5 minutes to ensure they are fresh.
</Tip>

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="connectionId" type="string" required>
        The connection ID.
    </ResponseField>
    <ResponseField name="forceRefresh" type="boolean">
        Defaults to `false`. If `false`, the token will only be refreshed if it expires within 15 minutes. If `true`, a token refresh attempt will happen on each request. This is only useful for testing and should not be done at high traffic.
    </ResponseField>
    <ResponseField name="refreshToken" type="boolean">
        Defaults to `false`. If `false`, the refresh token is not included in the response, otherwise it is. In production, it is not advised to return the refresh token, for security reasons, since only the access token is needed to sign requests.
    </ResponseField>
    <ResponseField name="refreshGithubAppJwtToken" type="boolean">
        Defaults to `false`. If true, this will refresh the JWT token for GitHub App / Github App OAuth connections
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "id": 18393,
    "created_at": "2023-03-08T09:43:03.725Z",
    "updated_at": "2023-03-08T09:43:03.725Z",
    "provider_config_key": "github",
    "connection_id": "1",
    "credentials": {
        "type": "OAUTH2",
        "access_token": "gho_tsXLG73f....",
        "refresh_token": "gho_fjofu84u9....",
        "expires_at": "2024-03-08T09:43:03.725Z",
        "raw": { // Raw token response from the OAuth provider: Contents vary!
            "access_token": "gho_tsXLG73f....",
            "refresh_token": "gho_fjofu84u9....",
            "token_type": "bearer",
            "scope": "public_repo,user"
        }
    },
    "connection_config": {
        "subdomain": "myshop",
        "realmId": "XXXXX",
        "instance_id": "YYYYYYY"
    },
    "metadata": {
        "myProperty": "yes",
        "filter": "closed=true"
    }
}
```
</Expandable>


### Patch a connection

Patch a connection.

```js
await nango.patchConnection({
    connectionId: '<CONNECTION-ID>',
    provider_config_key: '<INTEGRATION-ID>'
  },
  { ...body });
```

**Parameters**

<Expandable>
    <ResponseField name="body" type="PatchPublicConnection['Body']" required>
        The body of the connection (see [API Reference](/reference/api/connections/patch))
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "success": true
}
```
</Expandable>

### Get connection metadata

Returns a connection's metadata.

```js
await nango.getMetadata('<INTEGRATION-ID>', 'CONNECTION-ID');
```

If you know the structure of the metadata, you can specify a type;

```ts
interface CustomMetadata {
    anyKey: Record<string, string>;
}
const myTypedMetadata = await nango.getMetadata<CustomMetadata>('<INTEGRATION-ID>', '<CONNECTION-ID>');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID of the connection.
    </ResponseField>

    <ResponseField name="connectionId" type="string" required>
        The connection ID.
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "custom_key1": "custom_value1"
}
```
</Expandable>

### Set connection metadata

Set custom metadata for the connection or connections (overrides existing metadata).

```js
await nango.setMetadata('<INTEGRATION-ID>', 'CONNECTION-ID', { 'CUSTOM_KEY1': 'CUSTOM_VALUE1' });

# set an array of connection ids
await nango.setMetadata('<INTEGRATION-ID>', ['CONNECTION-ID', 'CONNECTION-ID-TWO'], { 'CUSTOM_KEY1': 'CUSTOM_VALUE1' });
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID of the connection.
    </ResponseField>

    <ResponseField name="connectionId" type="string | string[]" required>
        The connection ID or connection IDs.
    </ResponseField>

    <ResponseField name="metadata" type="Record<string, any>" required>
        The custom metadata to store in the connection.
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "connection_id": "<string | [string]>",
    "provider_config_key": "<string>",
    "metadata": {
        "CUSTOM_KEY1": "CUSTOM_VALUE1"
    }
}
```
</Expandable>

### Edit connection metadata

Edit custom metadata for the connection or connections. Only overrides specified properties, not the entire metadata.

```js
await nango.updateMetadata('<INTEGRATION-ID>', 'CONNECTION-ID', { 'CUSTOM_KEY1': 'CUSTOM_VALUE1' });

# update an array of connection ids
await nango.updateMetadata('<INTEGRATION-ID>', ['CONNECTION-ID', 'CONNECTION-ID-TWO'], { 'CUSTOM_KEY1': 'CUSTOM_VALUE1' });
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID of the connection.
    </ResponseField>

    <ResponseField name="connectionId" type="string | string[]" required>
        The connection ID or connection IDs.
    </ResponseField>

    <ResponseField name="metadata" type="Record<string, any>" required>
        The custom metadata to store in the connection.
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "connection_id": "<string | [string]>",
    "provider_config_key": "<string>",
    "metadata": {
        "CUSTOM_KEY1": "CUSTOM_VALUE1"
    }
}
```
</Expandable>

### Delete a connection

Deletes a specific connection.

```js
await nango.deleteConnection('<INTEGRATION-ID>', 'CONNECTION-ID');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID of the connection.
    </ResponseField>

    <ResponseField name="connectionId" type="string" required>
        The connection ID.
    </ResponseField>
</Expandable>

**Response**

Empty response.

### Wait for connection

Waits for a connection to be created for a given end user and integration. This is useful in agentic flows where you need to wait for a user to complete the OAuth flow before proceeding.

```js
const connection = await nango.waitForConnection('<INTEGRATION-ID>', '<END-USER-ID>');
```

<Tip>
This method polls for a connection every 2 seconds for up to 60 seconds (30 attempts). If no connection is found within this time, it will throw a timeout error.
</Tip>

**Parameters**

<Expandable>
    <ResponseField name="integrationKey" type="string" required>
        The integration ID (provider config key).
    </ResponseField>

    <ResponseField name="userId" type="string" required>
        The end user ID to wait for a connection for.
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "id": 1,
    "connection_id": "user-123",
    "provider": "slack",
    "provider_config_key": "slack-integration",
    "created": "2023-06-03T14:53:22.051Z",
    "metadata": null,
    "errors": [],
    "end_user": {
        "id": "user-123",
        "email": "user@example.com",
        "organization": {
            "id": "org-456"
        }
    }
}
```
</Expandable>

## Integration functions


### Get integration functions config

Return the configuration for all integration functions

```ts
const scriptsConfig = await nango.getScriptsConfig();
```

**Example Response**

<Expandable>
```json
[
    {
        "providerConfigKey": "demo-github-integration",
        "syncs": [
            {
                "name": "github-issue-example",
                "type": "sync",
                "models": [
                    {
                        "name": "GithubIssue",
                        "fields": [
                            {
                                "name": "id",
                                "type": "integer"
                            },
                            {
                                "name": "owner",
                                "type": "string"
                            },
                            {
                                "name": "repo",
                                "type": "string"
                            },
                            {
                                "name": "issue_number",
                                "type": "number"
                            },
                            {
                                "name": "title",
                                "type": "string"
                            },
                            {
                                "name": "author",
                                "type": "string"
                            },
                            {
                                "name": "author_id",
                                "type": "string"
                            },
                            {
                                "name": "state",
                                "type": "string"
                            },
                            {
                                "name": "date_created",
                                "type": "date"
                            },
                            {
                                "name": "date_last_modified",
                                "type": "date"
                            },
                            {
                                "name": "body",
                                "type": "string"
                            }
                        ]
                    }
                ],
                "sync_type": "FULL",
                "runs": "every half hour",
                "track_deletes": false,
                "auto_start": false,
                "last_deployed": "2024-02-28T20:16:38.052Z",
                "is_public": false,
                "pre_built": false,
                "version": "4",
                "attributes": {},
                "input": {},
                "returns": [
                    "GithubIssue"
                ],
                "description": "Fetches the Github issues from all a user's repositories.\nDetails: full sync, doesn't track deletes, metadata is not required.\n",
                "scopes": [
                    "public_repo"
                ],
                "endpoints": [
                    {
                        "GET": "/github/issue-example"
                    }
                ],
                "nango_yaml_version": "v2",
                "webhookSubscriptions": []
            }
        ],
        "actions": [
            {
                "name": "fetch-issues",
                "type": "action",
                "models": [
                    {
                        "name": "GithubIssue",
                        "fields": [
                            {
                                "name": "id",
                                "type": "integer"
                            },
                            {
                                "name": "owner",
                                "type": "string"
                            },
                            {
                                "name": "repo",
                                "type": "string"
                            },
                            {
                                "name": "issue_number",
                                "type": "number"
                            },
                            {
                                "name": "title",
                                "type": "string"
                            },
                            {
                                "name": "author",
                                "type": "string"
                            },
                            {
                                "name": "author_id",
                                "type": "string"
                            },
                            {
                                "name": "state",
                                "type": "string"
                            },
                            {
                                "name": "date_created",
                                "type": "date"
                            },
                            {
                                "name": "date_last_modified",
                                "type": "date"
                            },
                            {
                                "name": "body",
                                "type": "string"
                            }
                        ]
                    }
                ],
                "runs": "",
                "is_public": false,
                "pre_built": false,
                "version": "4",
                "last_deployed": "2024-02-28T20:16:38.052Z",
                "attributes": {},
                "returns": [
                    "GithubIssue"
                ],
                "description": "",
                "scopes": [],
                "input": {},
                "endpoints": [
                    {
                        "GET": "/github/issues"
                    }
                ],
                "nango_yaml_version": "v2"
            }
        ],
        "postConnectionScripts": [],
        "provider": "github"
    }
]
```
</Expandable>

You can also pass in an optional argument with the value of `nango` or `openai`. The default is `nango`

```ts
const scriptsConfig = await nango.getScriptsConfig('openai');
```
<Expandable>
```json
{
  "data": [
    {
      "name": "calendars",
      "description": "Sync the user's calendar list.\nIncludes all calendars the user has access to.",
      "parameters": {
        "type": "object",
        "properties": {},
        "required": []
      }
    },
    {
      "name": "events",
      "description": "Sync calendar events from the primary calendar.\nIncludes events from the past month.",
      "parameters": {
        "type": "object",
        "properties": {},
        "required": []
      }
    },
    {
      "name": "cancel-event",
      "description": "Cancel/delete an event by searching for it.\n\nInput parameters:\n- title: The title of the event to cancel\n- date: The date of the event in ISO format\n- time: The time of the event in 24-hour format (HH:mm)\n- calendar: Calendar ID where to search for the event\n- id: Calendar identifier\n- summary: Calendar name/title\n- description: Calendar description\n- location: Calendar location\n- timeZone: Time zone of the calendar\n- backgroundColor: Calendar color in UI\n- foregroundColor: Text color in UI\n- selected: Whether the calendar is selected in UI\n- accessRole: User's access role for the calendar\n- primary: Whether this is the primary calendar",
      "parameters": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Calendar identifier"
          },
          "summary": {
            "type": "string",
            "description": "Calendar name/title"
          },
          "description": {
            "type": "string",
            "description": "Calendar description"
          },
          "location": {
            "type": "string",
            "description": "Calendar location"
          },
          "timeZone": {
            "type": "string",
            "description": "Time zone of the calendar"
          },
          "backgroundColor": {
            "type": "string",
            "description": "Calendar color in UI"
          },
          "foregroundColor": {
            "type": "string",
            "description": "Text color in UI"
          },
          "selected": {
            "type": "boolean",
            "description": "Whether the calendar is selected in UI"
          },
          "accessRole": {
            "type": "string",
            "description": "User's access role for the calendar"
          },
          "primary": {
            "type": "boolean",
            "description": "Whether this is the primary calendar"
          },
          "title": {
            "type": "string",
            "description": "The title of the event to cancel"
          },
          "date": {
            "type": "string",
            "description": "The date of the event in ISO format"
          },
          "time": {
            "type": "string",
            "description": "The time of the event in 24-hour format (HH:mm)"
          },
          "calendar": {
            "type": "string",
            "description": "Calendar ID where to search for the event"
          }
        },
        "required": [
          "id",
          "summary"
        ]
      }
    },
    {
      "name": "create-event",
      "description": "Create a new calendar event.\n\nInput parameters:\n- summary: The title/summary of the event\n- description: A detailed description of the event\n- location: The location of the event\n- start: The start time of the event in ISO format\n- end: The end time of the event in ISO format\n- attendees: List of email addresses to invite\n- recurrence: List of recurrence rules in RRULE format\n- calendar: Calendar ID to create the event in\n- id: Calendar identifier\n- timeZone: Time zone of the calendar\n- backgroundColor: Calendar color in UI\n- foregroundColor: Text color in UI\n- selected: Whether the calendar is selected in UI\n- accessRole: User's access role for the calendar\n- primary: Whether this is the primary calendar",
      "parameters": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Calendar identifier"
          },
          "summary": {
            "type": "string",
            "description": "The title/summary of the event"
          },
          "description": {
            "type": "string",
            "description": "A detailed description of the event"
          },
          "location": {
            "type": "string",
            "description": "The location of the event"
          },
          "timeZone": {
            "type": "string",
            "description": "Time zone of the calendar"
          },
          "backgroundColor": {
            "type": "string",
            "description": "Calendar color in UI"
          },
          "foregroundColor": {
            "type": "string",
            "description": "Text color in UI"
          },
          "selected": {
            "type": "boolean",
            "description": "Whether the calendar is selected in UI"
          },
          "accessRole": {
            "type": "string",
            "description": "User's access role for the calendar"
          },
          "primary": {
            "type": "boolean",
            "description": "Whether this is the primary calendar"
          },
          "start": {
            "type": "string",
            "description": "The start time of the event in ISO format"
          },
          "end": {
            "type": "string",
            "description": "The end time of the event in ISO format"
          },
          "attendees": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of email addresses to invite"
          },
          "recurrence": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of recurrence rules in RRULE format"
          },
          "calendar": {
            "type": "string",
            "description": "Calendar ID to create the event in"
          }
        },
        "required": [
          "id",
          "summary",
          "start",
          "end"
        ]
      }
    },
    {
      "name": "move-event",
      "description": "Move an event to a different time or calendar.\n\nInput parameters:\n- eventId: The ID of the event to move\n- title: The title of the event to move\n- sourceStart: The current start time of the event\n- start: The new start time for the event in ISO format\n- end: The new end time for the event in ISO format\n- calendar: Calendar ID to move the event to\n- id: Calendar identifier\n- summary: Calendar name/title\n- description: Calendar description\n- location: Calendar location\n- timeZone: Time zone of the calendar\n- backgroundColor: Calendar color in UI\n- foregroundColor: Text color in UI\n- selected: Whether the calendar is selected in UI\n- accessRole: User's access role for the calendar\n- primary: Whether this is the primary calendar",
      "parameters": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Calendar identifier"
          },
          "summary": {
            "type": "string",
            "description": "Calendar name/title"
          },
          "description": {
            "type": "string",
            "description": "Calendar description"
          },
          "location": {
            "type": "string",
            "description": "Calendar location"
          },
          "timeZone": {
            "type": "string",
            "description": "Time zone of the calendar"
          },
          "backgroundColor": {
            "type": "string",
            "description": "Calendar color in UI"
          },
          "foregroundColor": {
            "type": "string",
            "description": "Text color in UI"
          },
          "selected": {
            "type": "boolean",
            "description": "Whether the calendar is selected in UI"
          },
          "accessRole": {
            "type": "string",
            "description": "User's access role for the calendar"
          },
          "primary": {
            "type": "boolean",
            "description": "Whether this is the primary calendar"
          },
          "eventId": {
            "type": "string",
            "description": "The ID of the event to move"
          },
          "title": {
            "type": "string",
            "description": "The title of the event to move"
          },
          "sourceStart": {
            "type": "string",
            "description": "The current start time of the event"
          },
          "start": {
            "type": "string",
            "description": "The new start time for the event in ISO format"
          },
          "end": {
            "type": "string",
            "description": "The new end time for the event in ISO format"
          },
          "calendar": {
            "type": "string",
            "description": "Calendar ID to move the event to"
          }
        },
        "required": [
          "id",
          "summary",
          "start",
          "end"
        ]
      }
    },
    {
      "name": "whoami",
      "description": "Get information about the authenticated user.\n\nNo input parameters.",
      "parameters": {
        "type": "object",
        "properties": {},
        "required": []
      }
    },
    {
      "name": "invite-user-to-repository",
      "description": "Invite a user to a GitHub repository.\n\nInput parameters:\n- owner: The owner (user or organization) of the repository\n- repo: The name of the repository to invite the user to\n- username: The GitHub username of the user to invite\n- permission: The permission level to grant (\"pull\", \"push\", \"admin\", \"maintain\", \"triage\")",
      "parameters": {
        "type": "object",
        "properties": {
          "owner": {
            "type": "string",
            "description": "The owner (user or organization) of the repository"
          },
          "repo": {
            "type": "string",
            "description": "The name of the repository to invite the user to"
          },
          "username": {
            "type": "string",
            "description": "The GitHub username of the user to invite"
          },
          "permission": {
            "type": "string",
            "description": "The permission level to grant (\"pull\", \"push\", \"admin\", \"maintain\", \"triage\")"
          }
        },
        "required": [
          "owner",
          "repo",
          "username"
        ]
      }
    }
  ]
}
```
</Expandable>

## Syncs

### Get records

Returns the synced data.

```ts
import type { ModelName } from '<path-to-nango-integrations>/models'

const records = await nango.listRecords<ModelName>({
    providerConfigKey: '<INTEGRATION-ID>',
    connectionId: '<CONNECTION-ID>',
    model: '<MODEL-NAME>'
});
```

**Parameters**

<Expandable>
  <ResponseField name="config" type="object" required>
    <Expandable title="config" defaultOpen>
      <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
      </ResponseField>

      <ResponseField name="connectionId" type="string" required>
        The connection ID.
      </ResponseField>

      <ResponseField name="model" type="string" required>
        The name of the model of the data you want to retrieve.
      </ResponseField>

      <ResponseField name="variant" type="string">
        The variant of the model to fetch. When omitted, the default base variant is used.
      </ResponseField>

      <ResponseField name="cursor" type="string">
        Each record from this endpoint comes with a synchronization cursor in `_nango_metadata.cursor`.

        Save the last fetched record's cursor to track how far you've synced.

        By providing the cursor to this method, you'll continue syncing from where you left off, receiving only post-cursor changes.

        This same cursor is used to paginate through the results of this endpoint.
      </ResponseField>

      <ResponseField name="limit" type="number">
        The maximum number of records to return. Defaults to 100.
      </ResponseField>

      <ResponseField name="filter" type="string">
        Filter to only show results that have been added or updated or deleted.

        Available options: added, updated, deleted
      </ResponseField>

      <ResponseField name="modifiedAfter" type="string">
        Timestamp, e.g. 2023-05-31T11:46:13.390Z. If passed, only records modified after this timestamp are returned, otherwise all records are returned.
      </ResponseField>

      <ResponseField name="ids" type="string[]">
        An array of string containing a list of your records IDs. The list will be filtered to include only the records with a matching ID.
      </ResponseField>

      <ResponseField name="delta" type="string">
        DEPRECATED (use modifiedAfter) Timestamp, e.g. 2023-05-31T11:46:13.390Z. If passed, only records modified after this timestamp are returned, otherwise all records are returned.
      </ResponseField>
    </Expandable>
  </ResponseField>
</Expandable>

**Example Response**

<Tip>
This endpoint returns a list of records, ordered by modification date ascending. If some records are updated while you paginate through this endpoint, you might see these records multiple times.
</Tip>

<Expandable>
```json
{
    records:
        [
            {
                id: 123,
                ..., // Fields as specified in the model you queried
                _nango_metadata: {
                    deleted_at: null,
                    last_action: 'ADDED',
                    first_seen_at: '2023-09-18T15:20:35.941305+00:00',
                    last_modified_at: '2023-09-18T15:20:35.941305+00:00',
                    cursor: 'MjAyNC0wMi0yNlQwMzowMDozOS42MjMzODgtMDU6MDB8fGVlMDYwM2E1LTEwNDktNDA4Zi05YTEwLTJjNzVmNDkwODNjYQ=='
                }
            },
            ...
        ],
    next_cursor: "Y3JlYXRlZF9hdF4yMDIzLTExLTE3VDExOjQ3OjE0LjQ0NyswMjowMHxpZF4xYTE2MTYwMS0yMzk5LTQ4MzYtYWFiMi1mNjk1ZWI2YTZhYzI"
}
```
</Expandable>

### Trigger sync(s)

Triggers an additional, one-off execution of specified sync(s) for a given connection or all applicable connections if no connection is specified.

```ts
// Simple usage with sync names
const result = await nango.triggerSync('<INTEGRATION-ID>', ['SYNC_NAME1', 'SYNC_NAME2'], '<CONNECTION_ID>', 'incremental');

// Using variants
const resultWithVariants = await nango.triggerSync('<INTEGRATION-ID>', [
  { name: 'SYNC_NAME1', variant: 'VARIANT_A' },
  'SYNC_NAME2' // Uses default base variant
], '<CONNECTION_ID>', 'incremental');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="syncs" type="Array<string | {name: string, variant: string}>" required>
        The name of the syncs to trigger. If the array is empty, all syncs are triggered.
        Each sync can be specified as either:
        - A string: the sync name (uses the default base variant)
        - An object: with name and variant properties to target a specific sync variant
    </ResponseField>
    <ResponseField name="connectionId" type="string">
        The connection ID. If omitted, the sync will trigger for all relevant connections.
    </ResponseField>
    <ResponseField name="sync_mode" type="'incremental' | 'full_refresh' | 'full_refresh_and_clear_cache'">
        The mode in which to trigger the syncs.
        - `incremental`: Triggers a new sync job while preserving the "lastSyncDate".
        - `full_refresh`: Resets the "lastSyncDate" associated with the sync before triggering a new sync job.
        - `full_refresh_and_clear_cache`: Resets the "lastSyncDate" and deletes all records associated with the sync before triggering a new sync job.
    </ResponseField>
</Expandable>

**Response**

Empty response.

### Start schedule for sync(s)

Starts the schedule of specified sync(s) for a given connection or all applicable connections if no connection is specified. Upon starting the schedule, the sync will execute immediately and then continue to run at the specified frequency. If the schedule was already started, this will have no effect.

```ts
// Simple usage with sync names
await nango.startSync('<INTEGRATION-ID>', ['SYNC_NAME1', 'SYNC_NAME2'], '<CONNECTION_ID>');

// Using variants
await nango.startSync('<INTEGRATION-ID>', [
  { name: 'SYNC_NAME1', variant: 'VARIANT_A' },
  'SYNC_NAME2' // Uses default base variant
], '<CONNECTION_ID>');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="syncs" type="Array<string | {name: string, variant: string}>" required>
        The name of the syncs that should be triggered.
        Each sync can be specified as either:
        - A string: the sync name (uses the default base variant)
        - An object: with name and variant properties to target a specific sync variant
    </ResponseField>
    <ResponseField name="connectionId" type="string">
        The connection ID. If omitted, the sync will trigger for all relevant connections.
    </ResponseField>
</Expandable>

**Response**

Empty response.

### Pause schedule for sync(s)

Pauses the schedule of specified sync(s) for a given connection or all applicable connections if no connection is specified.

```ts
// Simple usage with sync names
await nango.pauseSync('<INTEGRATION-ID>', ['SYNC_NAME1', 'SYNC_NAME2'], '<CONNECTION_ID>');

// Using variants
await nango.pauseSync('<INTEGRATION-ID>', [
  { name: 'SYNC_NAME1', variant: 'VARIANT_A' },
  'SYNC_NAME2' // Uses default base variant
], '<CONNECTION_ID>');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="syncs" type="Array<string | {name: string, variant: string}>" required>
        The name of the syncs that should be paused.
        Each sync can be specified as either:
        - A string: the sync name (uses the default base variant)
        - An object: with name and variant properties to target a specific sync variant
    </ResponseField>
    <ResponseField name="connectionId" type="string">
        The connection ID. If omitted, the sync will pause for all relevant connections.
    </ResponseField>
</Expandable>

**Response**

Empty response.

### Sync status

Get the status of specified sync(s) for a given connection or all applicable connections if no connection is specified.

```ts
// Simple usage with sync names
await nango.syncStatus('<INTEGRATION-ID>', ['SYNC_NAME1', 'SYNC_NAME2'], '<CONNECTION_ID>');

// Using variants
await nango.syncStatus('<INTEGRATION-ID>', [
  { name: 'SYNC_NAME1', variant: 'VARIANT_A' },
  'SYNC_NAME2' // Uses default base variant
], '<CONNECTION_ID>');

// Get all syncs
await nango.syncStatus('<INTEGRATION-ID>', '*', '<CONNECTION_ID>');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="syncs" type="string | Array<string | {name: string, variant: string}>" required>
        Either "*" to return all syncs, or an array of syncs to fetch status for.
        When using an array, each sync can be specified as either:
        - A string: the sync name (uses the default base variant)
        - An object: with name and variant properties to target a specific sync variant
    </ResponseField>
    <ResponseField name="connectionId" type="string">
        The connection ID. If omitted, all connections will be surfaced.
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "syncs": [
        {
            "id": "<string>",
            "connection_id": "<string>",
            "name": "<string>",
            "variant": "<string>",
            "status": "RUNNING",
            "type": "INCREMENTAL",
            "finishedAt": "<string>",
            "nextScheduledSyncAt": "<string>",
            "frequency": "<string>",
            "latestResult": {
                "<string>": {
                    "added": <number>,
                    "updated": <number>,
                    "deleted": <number>,
                }
            },
            "recordCount": {
                "<string>": <number>
                ...
            }
        }
    ]
}
```
</Expandable>

### Override sync connection frequency

Override a sync's default frequency for a specific connection, or revert to the default frequency.

```ts
// For base variant
await nango.updateSyncConnectionFrequency('<INTEGRATION-ID>', 'SYNC_NAME', '<CONNECTION_ID>', '<FREQUENCY>');

// For a specific variant
await nango.updateSyncConnectionFrequency('<INTEGRATION-ID>', { name: 'SYNC_NAME', variant: 'VARIANT_NAME' }, '<CONNECTION_ID>', '<FREQUENCY>');
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="sync" type="string | {name: string, variant: string}" required>
        The sync to update. Can be specified as either:
        - A string: the sync name (uses the default base variant)
        - An object: with name and variant properties to target a specific sync variant
    </ResponseField>
    <ResponseField name="connectionId" type="string" required>
        The connection ID.
    </ResponseField>
    <ResponseField name="frequency" type="string" required>
        The frequency you want to set (ex: 'every hour'). Set to `null` to revert to the default frequency.  Uses the https://github.com/vercel/ms notations. Min frequency: 5 minutes.
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "frequency": "<string>"
}
```
</Expandable>

### Create sync variant

Creates a new sync variant for a specific connection. Sync variants allow you to run multiple instances of the same sync with different configurations.

```ts
await nango.createSyncVariant({
  provider_config_key: '<INTEGRATION-ID>',
  connection_id: '<CONNECTION_ID>',
  name: 'SYNC_NAME',
  variant: 'VARIANT_NAME'
});
```

**Parameters**

<Expandable>
    <ResponseField name="props" type="object" required>
        <Expandable title="props" defaultOpen>
            <ResponseField name="provider_config_key" type="string" required>
                The integration ID.
            </ResponseField>
            <ResponseField name="connection_id" type="string" required>
                The connection ID.
            </ResponseField>
            <ResponseField name="name" type="string" required>
                The name of the sync.
            </ResponseField>
            <ResponseField name="variant" type="string" required>
                The name of the variant to create. Cannot be "base" (protected name).
            </ResponseField>
        </Expandable>
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "id": "12345",
    "name": "SYNC_NAME",
    "variant": "VARIANT_NAME"
}
```
</Expandable>

### Delete sync variant

Deletes a sync variant for a specific connection.

```ts
await nango.deleteSyncVariant({
  provider_config_key: '<INTEGRATION-ID>',
  connection_id: '<CONNECTION_ID>',
  name: 'SYNC_NAME',
  variant: 'VARIANT_NAME'
});
```

**Parameters**

<Expandable>
    <ResponseField name="props" type="object" required>
        <Expandable title="props" defaultOpen>
            <ResponseField name="provider_config_key" type="string" required>
                The integration ID.
            </ResponseField>
            <ResponseField name="connection_id" type="string" required>
                The connection ID.
            </ResponseField>
            <ResponseField name="name" type="string" required>
                The name of the sync.
            </ResponseField>
            <ResponseField name="variant" type="string" required>
                The name of the variant to delete. Cannot be "base" (protected name).
            </ResponseField>
        </Expandable>
    </ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
    "success": true
}
```
</Expandable>

### Get environment variables

Retrieve the environment variables as added in the Nango dashboard.

```js
await nango.getEnvironmentVariables();
```

**Parameters**

No parameters.

**Response**

<Expandable>
```json
[
    {
        "name": "MY_SECRET_KEY",
        "value": "SK_373892NSHFNCOWFO..."
    }
]
```
</Expandable>

## Actions

### Trigger an action

Triggers an action for a connection.

```js
await nango.triggerAction('<INTEGRATION-ID>', '<CONNECTION_ID>', '<ACTION-NAME>', { 'custom_key1': 'custom_value1' });
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="connectionId" type="string" required>
        The connection ID.
    </ResponseField>
    <ResponseField name="actionName" type="string" required>
        The name of the action to trigger.
    </ResponseField>
    <ResponseField name="input" type="unknown">
        The necessary input for your action's `exec` function.
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "your-properties": "The data returned by the action"
}
```
</Expandable>

<Warning>
The output of an action cannot exceed 10MB.
</Warning>

### Trigger an action asynchronously

Triggers an action asynchronously for a connection. This allows you to start an action and retrieve the results later.

```js
const { id, statusUrl } = await nango.triggerActionAsync('<INTEGRATION-ID>', '<CONNECTION_ID>', '<ACTION-NAME>', { 'custom_key1': 'custom_value1' });
```

**Parameters**

<Expandable>
    <ResponseField name="providerConfigKey" type="string" required>
        The integration ID.
    </ResponseField>
    <ResponseField name="connectionId" type="string" required>
        The connection ID.
    </ResponseField>
    <ResponseField name="actionName" type="string" required>
        The name of the action to trigger.
    </ResponseField>
    <ResponseField name="input" type="unknown">
        The necessary input for your action's `exec` function.
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "id": "action_123456",
    "statusUrl": "/action/action_123456"
}
```
</Expandable>

### Get async action result

Retrieves the result of an asynchronous action.

```js
// Using the id
const result = await nango.getAsyncActionResult({ id: 'action_123456' });

// OR using the statusUrl
const result = await nango.getAsyncActionResult({ statusUrl: '/action/action_123456' });
```

**Parameters**

<Expandable>
    <ResponseField name="props" type="object" required>
        <Expandable title="props" defaultOpen>
            <ResponseField name="id" type="string">
                The ID of the action to retrieve the result for.
            </ResponseField>
            <ResponseField name="statusUrl" type="string">
                The URL where the result can be retrieved.
            </ResponseField>
        </Expandable>
    </ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
    "your-properties": "The data returned by the action"
}
```
</Expandable>

## Proxy

Makes an HTTP request using the [proxy](/guides/use-cases/proxy):

```js
const config = {
    endpoint: '/some-endpoint',
    providerConfigKey: '<INTEGRATION-ID>',
    connectionId: '<CONNECTION-ID>'
};

await nango.get(config); // GET request
await nango.post(config); // POST request
await nango.put(config); // PUT request
await nango.patch(config); // PATCH request
await nango.delete(config); // DELETE request
```

**Parameters**

<Expandable>
    <ResponseField name="config" type="object" required>
        <Expandable title="config" defaultOpen>
            <ResponseField name="endpoint" type="string" required>
                The endpoint of the request.
            </ResponseField>
            <ResponseField name="providerConfigKey" type="string" required>
                The integration ID (for credential injection).
            </ResponseField>
            <ResponseField name="connectionId" type="string" required>
                The connection ID (for credential injection).
            </ResponseField>
            <ResponseField name="headers" type="Record<string, string>">
                The headers of the request.
            </ResponseField>
            <ResponseField name="params" type="Record<string, string | number>">
                The query parameters of the request.
            </ResponseField>
            <ResponseField name="data" type="unknown">
                The body of the request.
            </ResponseField>
            <ResponseField name="retries" type="number">
                The number of retries in case of failure (with exponential back-off). Optional, default 0.
            </ResponseField>
            <ResponseField name="retryOn" type="number[]">
                Array of additional status codes to retry a request in addition to the 5xx, 429, ECONNRESET, ETIMEDOUT, and ECONNABORTED
            </ResponseField>
            <ResponseField name="baseUrlOverride" type="string">
                The API base URL. Can be omitted if the base URL is configured for this API in the [providers.yaml](https://nango.dev/providers.yaml).
            </ResponseField>
            <ResponseField name="decompress" type="boolean">
                Override the decompress option when making requests. Optional, defaults to false
            </ResponseField>
            <ResponseField name="responseType" type="'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'">
                The type of the response.
            </ResponseField>
        </Expandable>
    </ResponseField>
</Expandable>

**Response**

<Expandable>
The response from the external API is passed back to you exactly as Nango gets it:
- response code
- response headers
- response body
</Expandable>

## Connect

### Create a connect session

Create a connect session for a given end user. The token is short-lived and lasts for 30 minutes.

```js
const { data } = await nango.createConnectSession({
  end_user: {
    id: '<END-USER-ID>',
    email: '<END-USER-EMAIL>',
    display_name: '<END-USER-NAME>',
    tags: { organizationId: '<ORGANIZATION-ID>' }
  },
  allowed_integrations: ['<INTEGRATION-ID-1>', '<INTEGRATION-ID-2>'],
  integrations_config_defaults: {
    <INTEGRATION-ID-1>: {
      connection_config: {
        <CONFIG-KEY>: '<VALUE>'
      }
    }
  }
});
```

**Parameters**

<Expandable>
  <ResponseField name="end_user" type="object" required>
    <Expandable title="end_user" defaultOpen>
      <ResponseField name="id" type="string" required>
        The unique identifier for the end user.
      </ResponseField>
      <ResponseField name="email" type="string">
        The email address of the end user.
      </ResponseField>
      <ResponseField name="display_name" type="string">
        The display name of the end user.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="organization" type="object">
    <Expandable title="organization" defaultOpen>
      <ResponseField name="id" type="string" required>
        The unique identifier for the organization.
      </ResponseField>
      <ResponseField name="display_name" type="string">
        The display name of the organization.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="allowed_integrations" type="string[]">
    An array of integration IDs that are allowed for this session.
  </ResponseField>

  <ResponseField name="integrations_config_defaults" type="object">
    Default configuration for specific integrations.
  </ResponseField>
</Expandable>

**Returns**

<Expandable>
```json
{
    "data": {
        "token": "nango_connect_session_4603dbca8a588315ba69b5bfddde52e72d312dc2d2870bd5e45da6357333601c",
        "connect_link": "https://connect.nango.dev/?session_token=nango_connect_session_4603dbca8a588315ba69b5bfddde52e72d312dc2d2870bd5e45da6357333601c",
        "expires_at": "2024-09-27T19:49:51.449Z"
    }
}
```
</Expandable>


### Create a reconnect session

Create a reconnect session for a given `connection_id`. Optionally, you can set `end_user` and `organization` to update those attributes of the connection.
Use this method when a user needs to input new credentials or to manually refresh token.

<Info>This method is only compatible with `connection_id` created with a session token.</Info>

```js
const { data } = await nango.createReconnectSession({
  // Required
  connection_id: '<CONNECTION-ID>'
  integration_id: '<INTEGRATION-ID>',

  // Optional
  end_user: {
    id: '<END-USER-ID>',
    email: '<END-USER-EMAIL>',
    display_name: '<END-USER-NAME>',
    tags: { organizationId: '<ORGANIZATION-ID>' }
  },
  integrations_config_defaults: {
    <INTEGRATION-ID-1>: {
      connection_config: {
        <CONFIG-KEY>: '<VALUE>'
      }
    }
  }
});
```

**Parameters**

<Expandable>
  <ResponseField name="connection_id" type="string" required>
    The unique identifier for the connection.
  </ResponseField>

  <ResponseField name="integration_id" type="string" required>
    The unique identifier for the integration.
  </ResponseField>

  <ResponseField name="end_user" type="object">
    <Expandable title="end_user">
      <ResponseField name="id" type="string" required>
        The unique identifier for the end user.
      </ResponseField>
      <ResponseField name="email" type="string">
        The email address of the end user.
      </ResponseField>
      <ResponseField name="display_name" type="string">
        The display name of the end user.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="organization" type="object">
    <Expandable title="organization">
      <ResponseField name="id" type="string" required>
        The unique identifier for the organization.
      </ResponseField>
      <ResponseField name="display_name" type="string">
        The display name of the organization.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <ResponseField name="integrations_config_defaults" type="object">
    Default configuration for specific integrations.
  </ResponseField>
</Expandable>

**Returns**

<Expandable>
```json
{
    "data": {
        "token": "nango_connect_session_4603dbca8a588315ba69b5bfddde52e72d312dc2d2870bd5e45da6357333601c",
        "connect_link": "https://connect.nango.dev/?session_token=nango_connect_session_4603dbca8a588315ba69b5bfddde52e72d312dc2d2870bd5e45da6357333601c",
        "expires_at": "2024-09-27T19:49:51.449Z"
    }
}
```
</Expandable>

## Webhooks from Nango

### Verify Webhook Signature

Asserts that a Webhook is coming from Nango's backend.

```js
async (req, res) => {
    const isValid = nango.verifyIncomingWebhookRequest(req.body, req.headers);
}
```


<Tip>
**Questions, problems, feedback?** Please reach out in the [Slack community](https://nango.dev/slack).
</Tip>
